home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / TreeView / String.m < prev    next >
Text File  |  1995-06-12  |  8KB  |  377 lines

  1. //
  2. //    String.m -- a generic class to simplify manipulation of (char *)'s
  3. //        Written by Don Yacktman (c) 1993 by Don Yacktman.
  4. //                Version 1.1.  All rights reserved.
  5. //
  6. //        You may use and copy this class freely as long as you
  7. //        comply with the following terms:
  8. //            (1) If you use this class in an application which you
  9. //                intend to sell commercially, as shareware, or otherwise,
  10. //                you may only do so with express written permission
  11. //                of the author.  Use in applications which will
  12. //                be distributed free of charge is encouraged.
  13. //            (2) You must include the source code to this object and
  14. //                all accompanying documentation with your application,
  15. //                or provide it to users if requested, free of charge.
  16. //            (3) Do not remove the author's name or any of the
  17. //                copyright notices
  18. //
  19.  
  20. #import "String.h"
  21. #import <strings.h>
  22. #import <appkit/appkit.h>
  23.  
  24. @implementation String
  25.  
  26. - init
  27. {
  28.      [super init];
  29.      [self setStringOrderTable:NXDefaultStringOrderTable()];
  30.      buffer = NULL;
  31.      length = 0;
  32.      _length = 0;
  33.      return self;
  34. }
  35.  
  36. - initString:(const char *)aString
  37. {
  38.     [self init];
  39.     return [self setString:aString];
  40. }
  41.  
  42. - setStringOrderTable:(NXStringOrderTable *)table
  43. {
  44.     orderTable = table;
  45.     return self;
  46. }
  47.  
  48. - (NXStringOrderTable *)stringOrderTable
  49. {
  50.     return orderTable;
  51. }
  52.  
  53. - allocateBuffer:(int)size
  54. {
  55.     return [self allocateBuffer:size fromZone:[self zone]];
  56. }
  57.  
  58. - allocateBuffer:(int)size fromZone:(NXZone *)zone
  59. {
  60.     if (size <= _length) return self;
  61.     [self freeString];
  62.     buffer = (char *)NXZoneMalloc(zone, size);
  63.     buffer[0] = 0;
  64.     _length = size;
  65.  
  66.     return self;
  67. }
  68.  
  69. - setString:(const char *)aString
  70. {
  71.     return [self setString:aString fromZone:[self zone]];
  72. }
  73.  
  74. - setString:(const char *)aString fromZone:(NXZone *)zone
  75. {
  76.     if (!aString) return self;
  77.     // Note that I could have used NXCopyStringBufferFromZone() here
  78.     // instead.  This works just as well, but it may be slower...
  79.     // I haven't checked that out, though.  It might be worth doing.
  80.     [self allocateBuffer:strlen(aString)+1 fromZone:zone];
  81.     strcpy(buffer, aString);
  82.     length = strlen(buffer);
  83.     return self;
  84. }
  85.  
  86. - setStringValue:sender
  87. {
  88.     if (![sender respondsTo:@selector(stringValue)]) return self;
  89.     return [self setString:[sender stringValue] fromZone:[self zone]];
  90. }
  91.  
  92. - setStringValue:sender fromZone:(NXZone *)zone
  93. {
  94.     if (![sender respondsTo:@selector(stringValue)]) return self;
  95.     return [self setString:[sender stringValue] fromZone:zone];
  96. }
  97.  
  98. - (const char *)stringValue
  99. {
  100.     return buffer;
  101. }
  102.  
  103. - read:(NXTypedStream *)stream
  104. {
  105.     char *tmpStr;
  106.     [super read:stream];
  107.     NXReadType(stream, "i", &_length);
  108.     tmpStr = (char *)malloc(_length + 1);
  109.     NXReadType(stream, "*", &tmpStr);
  110.     [self setString:tmpStr fromZone:[self zone]];
  111.     free(tmpStr);
  112.     return self;
  113. }
  114.  
  115. - write:(NXTypedStream *)stream
  116. {
  117.     [super write:stream];
  118.     NXWriteTypes(stream, "i*", &_length, &buffer);
  119.     return self;
  120. }
  121.  
  122. - copyFromZone:(NXZone *)zone
  123. {
  124.     String *myCopy = [super copyFromZone:zone];
  125.     // force child to have it's own copy of the string buffer
  126.     [myCopy _unhookBuffer];
  127.     [myCopy allocateBuffer:_length fromZone:zone];
  128.     [myCopy setString:buffer fromZone:zone];
  129.     return myCopy;
  130. }
  131.  
  132. - _unhookBuffer
  133. { // used by the copy method so that we don't free the buffer from orig. 
  134.     buffer = NULL; _length = 0;
  135.     return self;
  136. }
  137.  
  138. - freeString
  139. {
  140.     if(buffer) free(buffer);
  141.     buffer = NULL;
  142.     length = 0;
  143.     _length = 0;
  144.     return self;
  145. }
  146.  
  147. - free
  148. {
  149.      [self freeString];
  150.      return [super free];
  151. }
  152.  
  153. - cat:(const char *)aString
  154. {
  155.     return [self cat:aString
  156.                  n:strlen(aString)
  157.                  fromZone:[self zone]];
  158. }
  159.  
  160. - cat:(const char *)aString n:(int)n
  161. {
  162.     return [self cat:aString n:n fromZone:[self zone]];
  163. }
  164.  
  165. - cat:(const char *)aString fromZone:(NXZone *)zone
  166. {
  167.     return [self cat:aString n:strlen(aString) fromZone:zone];
  168. }
  169.  
  170. - cat:(const char *)aString n:(int)n fromZone:(NXZone *)zone
  171. {
  172.     char *newBuffer; int newSize;
  173.     newSize = length + n + 1;
  174.     if (newSize > _length) {
  175.         newBuffer = (char *)NXZoneMalloc(zone, newSize);
  176.         _length = newSize;
  177.         newBuffer[0] = '\0';
  178.         strcat(newBuffer, buffer);
  179.         strncat(newBuffer, aString, n);
  180.         free(buffer);
  181.         buffer = newBuffer;
  182.     } else  strncat(buffer, aString, n);
  183.     length = strlen(buffer);
  184.     return self;
  185. }
  186.  
  187. - concatenate:sender
  188. {
  189.     if (![sender respondsTo:@selector(stringValue)]) return self;
  190.     return [self cat:[sender stringValue]
  191.                  n:strlen([sender stringValue])
  192.                  fromZone:[self zone]];
  193. }
  194.  
  195. - concatenate:sender n:(int)n
  196. {
  197.     if (![sender respondsTo:@selector(stringValue)]) return self;
  198.     return [self cat:[sender stringValue] n:n fromZone:[self zone]];
  199. }
  200.  
  201. - concatenate:sender fromZone:(NXZone *)zone
  202. {
  203.     if (![sender respondsTo:@selector(stringValue)]) return self;
  204.     return [self cat:[sender stringValue]
  205.             n:strlen([sender stringValue]) fromZone:zone];
  206. }
  207.  
  208. - concatenate:sender n:(int)n fromZone:(NXZone *)zone
  209. {
  210.     if (![sender respondsTo:@selector(stringValue)]) return self;
  211.     return [self cat:[sender stringValue] n:n fromZone:zone];
  212. }
  213.  
  214. - (const char *)rindex:(char)aChar
  215. {
  216.     return rindex(buffer, aChar);
  217. }
  218.  
  219. - (const char *)index:(char)aChar
  220. {
  221.     return index(buffer, aChar);
  222. }
  223.  
  224. - (const char *)strstr:(const char *)subString
  225. {
  226.     return strstr(buffer, subString);
  227. }
  228.  
  229. - subStringRight:subString
  230. {
  231.     const char *sub;
  232.     if ([subString respondsTo:@selector(stringValue)])
  233.         sub = [subString stringValue];
  234.     else return nil;    // error if can't get string value
  235.     return [[String allocFromZone:[self zone]]
  236.             initString:strstr(buffer, sub)];
  237. }
  238.  
  239. - subStringLeft:subString
  240. {
  241.     const char *sub;
  242.     char *tempString = NXCopyStringBufferFromZone(buffer, [self zone]);
  243.     char *temp2;
  244.     id retVal = [String alloc];
  245.     
  246.     if ([subString respondsTo:@selector(stringValue)])
  247.         sub = [subString stringValue];
  248.     else return nil;    // error if can't get string value
  249.     temp2 = strstr(tempString, sub); 
  250.     if (temp2) {
  251.         temp2[0] = '\0';    // terminate it early
  252.         [retVal initString:tempString];
  253.     } else { // substring not found
  254.         return [self copy];
  255.     }
  256.     free(tempString);
  257.     return retVal;
  258. }
  259.  
  260. - (int)length
  261. {
  262.     return length;
  263. }
  264.  
  265. - (BOOL)isEqual:anObject
  266. {
  267.     if (anObject == self) return YES;
  268.     // doesn't have to be a String object to be equal...
  269.     if ([anObject respondsTo:@selector(stringValue)]) {
  270.         if (!NXOrderStrings(buffer, [anObject stringValue],
  271.                 YES, -1, orderTable)) return YES;
  272.     }
  273.     return NO;
  274. }
  275.  
  276. - (int)compareTo:sender
  277. {
  278.     return [self compareTo:sender n:(-1) caseSensitive:YES];
  279. }
  280.  
  281. - (int)compareTo:sender n:(int)n
  282. {
  283.     return [self compareTo:sender n:n caseSensitive:YES];
  284. }
  285.  
  286. - (int)cmp:(const char *)aString
  287. {
  288.     return strcmp(buffer, aString);
  289. }
  290.  
  291. - (int)cmp:(const char *)aString n:(int)n
  292. {
  293.     return strncmp(buffer, aString, n);
  294. }
  295.  
  296. - (int)compareTo:sender caseSensitive:(BOOL)sense
  297. {
  298.     return [self compareTo:sender n:(-1) caseSensitive:sense];
  299. }
  300.  
  301. - (int)compareTo:sender n:(int)n caseSensitive:(BOOL)sense
  302. {
  303.     if (![sender respondsTo:@selector(stringValue)]) return 1; // !=
  304.     return NXOrderStrings(buffer, [sender stringValue], sense, n, orderTable);
  305. }
  306.  
  307. - (int)casecmp:(const char *)aString
  308. {
  309.     return strcasecmp(buffer, aString);
  310. }
  311.  
  312. - (int)casecmp:(const char *)aString n:(int)n
  313. {
  314.     return strncasecmp(buffer, aString, n);
  315. }
  316.  
  317. - left:(int)count
  318. {
  319.     return [self left:count fromZone:[self zone]];
  320. }
  321.  
  322. - right:(int)count
  323. {
  324.     return [self right:count fromZone:[self zone]];
  325. }
  326.  
  327. - midFrom:(int)start to:(int)end
  328. {
  329.     return [self midFrom:start to:end fromZone:[self zone]];
  330. }
  331.  
  332. - midFrom:(int)start length:(int)len
  333. {
  334.     return [self midFrom:start length:len fromZone:[self zone]];
  335. }
  336.  
  337. - left:(int)count fromZone:(NXZone *)zone
  338. {
  339.     char smash = buffer[count];
  340.     id newString = [[String allocFromZone:zone] init];
  341.     buffer[count] = '\0';
  342.     [newString setString:buffer fromZone:zone];
  343.     buffer[count] = smash;
  344.     return newString;
  345. }
  346.  
  347. - right:(int)count fromZone:(NXZone *)zone
  348. {
  349.     id newString = [[String allocFromZone:zone] init];
  350.     [newString setString:&buffer[length - count] fromZone:zone];
  351.     return newString;
  352. }
  353.  
  354. - midFrom:(int)start to:(int)end fromZone:(NXZone *)zone
  355. {
  356.     char smash = buffer[end];
  357.     id newString = [[String allocFromZone:zone] init];
  358.     buffer[end] = '\0'; // inclusive; end-1 is not.
  359.     [newString setString:&buffer[start - 1] fromZone:zone];
  360.     buffer[end] = smash;
  361.     return newString;
  362. }
  363.  
  364. - midFrom:(int)start length:(int)len fromZone:(NXZone *)zone
  365. {
  366.     register int spot = start + len - 1;
  367.     char smash = buffer[spot];
  368.     id newString = [[String allocFromZone:zone] init];
  369.     buffer[spot] = '\0';
  370.     [newString setString:&buffer[start - 1] fromZone:zone];
  371.     buffer[spot] = smash;
  372.     return newString;
  373. }
  374.  
  375.  
  376. @end
  377.